package chan.project.service.impl;

import chan.project.exception.BusinessException;
import chan.project.model.entity.TravelPlan;
import chan.project.service.TravelPlanService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import chan.project.common.ErrorCode;
import chan.project.mapper.TravelPlanThumbMapper;
import chan.project.model.entity.TravelPlanThumb;
import chan.project.model.entity.User;
import chan.project.service.TravelPlanThumbService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 旅行计划点赞服务实现
 *
 * @author <a href="https://github.com/kavansp">kavansp</a>
 *
 */
@Service
@Slf4j
public class TravelPlanThumbServiceImpl extends ServiceImpl<TravelPlanThumbMapper, TravelPlanThumb> implements TravelPlanThumbService {

    @Resource
    @Lazy
    private TravelPlanService travelPlanService;

    /**
     * 点赞
     *
     * @param postId
     * @param loginUser
     * @return
     */
    @Override
    public int doTravelPlanThumb(long postId, User loginUser) {
        // 判断实体是否存在，根据类别获取实体
        TravelPlan travelPlan = travelPlanService.getById(postId);
        if (travelPlan == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 是否已点赞
        long userId = loginUser.getId();
        // 每个用户串行点赞
        // 锁必须要包裹住事务方法
        TravelPlanThumbService travelPlanThumbService = (TravelPlanThumbService) AopContext.currentProxy();
        synchronized (String.valueOf(userId).intern()) {
            return travelPlanThumbService.doTravelPlanThumbInner(userId, postId);
        }
    }

    /**
     * 封装了事务的方法
     *
     * @param userId
     * @param travelPlanId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int doTravelPlanThumbInner(long userId, long travelPlanId) {
        TravelPlanThumb travelPlanThumb = new TravelPlanThumb();
        travelPlanThumb.setUserId(userId);
        travelPlanThumb.setTravelPlanId(travelPlanId);
        QueryWrapper<TravelPlanThumb> thumbQueryWrapper = new QueryWrapper<>(travelPlanThumb);
        TravelPlanThumb oldPostThumb = this.getOne(thumbQueryWrapper);
        boolean result;
        // 已点赞
        if (oldPostThumb != null) {
            result = this.remove(thumbQueryWrapper);
            if (result) {
                // 点赞数 - 1
                result = travelPlanService.update()
                        .eq("id", travelPlanId)
                        .gt("thumbNum", 0)
                        .setSql("thumbNum = thumbNum - 1")
                        .update();
                return result ? -1 : 0;
            } else {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR);
            }
        } else {
            // 未点赞
            result = this.save(travelPlanThumb);
            if (result) {
                // 点赞数 + 1
                result = travelPlanService.update()
                        .eq("id", travelPlanId)
                        .setSql("thumbNum = thumbNum + 1")
                        .update();
                return result ? 1 : 0;
            } else {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR);
            }
        }
    }

}
